#include "BodyMesh.h"

#include "libs/tinyxml/tinyxml.h"
#include "../src/pw_exception.h"
#include <string>
#include <boost/lexical_cast.hpp>

BodyMesh::BodyMesh(const std::string& file)
{
	using std::string;
	using boost::lexical_cast;
	using boost::bad_lexical_cast;
	using physicsworks::exception::IException;
	
	TiXmlDocument doc(file);
	doc.LoadFile();
	TiXmlHandle docHandle( &doc );
	TiXmlElement* submesh0 = docHandle.FirstChild("mesh").FirstChild("submeshes").FirstChild("submesh").Element();
	if (submesh0 == 0)		
		throw new IException("Could not load " + file);
	
	TiXmlElement* faces = submesh0->FirstChildElement("faces");
	if (faces == 0)
		throw new IException("Could not load " + file);

	TiXmlElement* geo = submesh0->FirstChildElement("geometry");
	if (geo == 0)
		throw new IException("Could not load " + file);
	
	const char* vc = geo->Attribute("vertexcount");
	if (vc == 0)
		throw new IException("Could not load " + file);
	
	TiXmlElement* vertBuff = geo->FirstChildElement("vertexbuffer");
	if (vertBuff == 0)
		throw new IException("Could not load " + file);
	
	int numVerts;
	
	try {
		numVerts = lexical_cast<int>(vc);
	} catch (bad_lexical_cast&) {
		throw new IException("Could not load " + file);
	}
	
	if (numVerts <= 0)
		throw new IException("Could not load " + file);
	
	numVertices = numVerts;
	vertX = new real[numVerts];
	vertY = new real[numVerts];
	vertZ = new real[numVerts];
	
	TiXmlElement* vert = vertBuff->FirstChildElement("vertex");
	if (vert == 0)
		throw new IException("Could not load " + file);
	
	int i = 0;
	do {
		TiXmlElement* pos = vert->FirstChildElement("position");
		if (pos == 0)
			throw new IException("Could not load " + file);
		
		const char* xStr = pos->Attribute("x");
		if (xStr == 0) throw new IException("Could not load " + file);
		const char* yStr = pos->Attribute("y");
		if (yStr == 0) throw new IException("Could not load " + file);
		const char* zStr = pos->Attribute("z");
		if (zStr == 0) throw new IException("Could not load " + file);
		
		real x, y, z;
		try {
			x = lexical_cast<real>(xStr);
			y = lexical_cast<real>(yStr);
			z = lexical_cast<real>(zStr);
		} catch (bad_lexical_cast&) {
			throw new IException("Could not load " + file);
		}
		
		vertX[i] = x;
		vertY[i] = y;
		vertZ[i] = z;
		
		vert = vert->NextSiblingElement("vertex");
		++i;
	} while (vert != 0 && i < numVerts);
	
	if ( !(vert == 0 && numVerts == i) )
		throw new IException("Could not load " + file);
	
	const char* fcStr = faces->Attribute("count");
	if (fcStr == 0)
		throw new IException("Could not load " + file);
	
	int numFs = lexical_cast<int>(fcStr);
	
	if (numFs <= 0)
		throw new IException("Could not load " + file);
	
	numFaces = numFs;
	verticesIndices = new int[3 * numFs];
	
	TiXmlElement* face = faces->FirstChildElement("face");
	if (face == 0)
		throw new IException("Could not load " + file);

	i = 0;
	do {
		const char* v0Str = face->Attribute("v1");
		if (v0Str == 0) throw new IException("Could not load " + file);
		const char* v1Str = face->Attribute("v2");
		if (v1Str == 0) throw new IException("Could not load " + file);
		const char* v2Str = face->Attribute("v3");
		if (v2Str == 0) throw new IException("Could not load " + file);
		
		int v0, v1, v2;
		try {
			v0 = lexical_cast<int>(v0Str);
			v1 = lexical_cast<int>(v1Str);
			v2 = lexical_cast<int>(v2Str);
		} catch (bad_lexical_cast&) {
			throw new IException("Could not load " + file);
		}
		
		verticesIndices[3*i + 0] = v0;
		verticesIndices[3*i + 1] = v1;
		verticesIndices[3*i + 2] = v2;
		
		face = face->NextSiblingElement("face");
		++i;
	} while (face != 0 && i < numFs);
	
	if ( !(face == 0 && numFs == i) )
		throw new IException("Could not load " + file);
}

BodyMesh::~BodyMesh()
{
	delete [] vertX;
	delete [] vertY;
	delete [] vertZ;
	delete [] verticesIndices;
}

/*
 * old version
#include "libs/3dsreader/l3ds.h"

BodyMesh::BodyMesh(const std::string& file)
{
	L3DS loader;
	
	if (!loader.LoadFile(file.c_str()))
		return;
	
	LMesh& m = loader.GetMesh(0);

	numVertices = m.GetVertexCount();
	
	vertX = new real[numVertices];
	vertY = new real[numVertices];
	vertZ = new real[numVertices];
	
	for (int i = 0; i < numVertices; ++i) {
		const LVector4& v = m.GetVertex(i);
		vertX[i] = v.x;
		vertY[i] = v.y;
		vertZ[i] = v.z;
	}

	numFaces = m.GetTriangleCount();
	
	verticesIndices = new int[numFaces * 3];
	
	for (int i = 0; i < numFaces; ++i) {
		const LTriangle& t = m.GetTriangle(i);
		verticesIndices[3*i + 0] = t.a;
		verticesIndices[3*i + 1] = t.b;
		verticesIndices[3*i + 2] = t.c;
	}
}
*/
